import createDOMString from '../../utils/createDOMString';
import CMSElement from '../../utils/CMSElement';

/**
 * @param page-size            √每页显示的条目数量
 * @param total               √总条目数
 * 
 * @param pager-count          √最大页码数量（超过此数量时会省略）（默认向上取奇数）,最小为3
 * @param current-page         √当前页码,可通过此属性更改默认展示的页码  
 * @param page-sizes           √每页显示条目数选择器的范围【10，20，30】
 *
 * @event current-change       √当前页码改变时的回调
 * @event prev-click           √上一页按钮
 * @event next-click           √下一页按钮
 */

const ellipsis = `
  <svg
    class="cms-pagination-icon"
    viewBox="0 0 1024 1024"
    width="25"
    height="25"
  >
    <path 
      d="M221 592c-44.183 0-80-35.817-80-80s35.817-80 80-80 80 35.817 80 80-35.817 80-80 80z m291 0c-44.183 0-80-35.817-80-80s35.817-80 80-80 80 35.817 80 80-35.817 80-80 80z m291 0c-44.183 0-80-35.817-80-80s35.817-80 80-80 80 35.817 80 80-35.817 80-80 80z"
      fill="#606266"
    ></path>
  </svg>`;

function RateEvent(type,value) {
  return new CustomEvent(`${type}`, {
    detail: {
      value,
    },
  });
}
class CmsPagination extends CMSElement {
  props = {
    //number类型属性
    pageSize: 5,
    pageSizes: [],
    total: 0,
    pageCount: 1,
    pagerCount: 3, //数字页码按钮一共三个
    currentPage: 1,
    //事件相关属性：
    currentChange: '',
    prevClick: '',
    nextClick: '',
  };
  //使用set和get同步props值和元素属性值
  get pageSize() {
    return this.props.pageSize;
  }
  set pageSize(val) {
    this.setAttribute('page-size', val);
    //这里放sizeChange回调函数
  }
  get currentPage() {
    return this.props.currentPage;
  }
  //在这个函数里面执行传入的currentChange回调函数
  set currentPage(val) {
    this.setAttribute('current-page', val);
    this.dispatchEvent(RateEvent('current-change',this.props));
  }
  //监听元素标签属性变化并进行相关操作
  static get observedAttributes() {
    return [
      'page-size',
      'total',
      'current-page',
      'pager-count',
      'page-sizes',
    ];
  }
  attributeChangedCallback(name, last, cur) {
    if (name === 'page-size') {
      if (this.isPositiveInteger(cur)) {
        this.props.pageSize = Math.round(Number(cur));
        this.props.total
          ? (this.props.pageCount = Math.ceil(this.props.total / this.props.pageSize))
          : null;
        this.currentPage = 1;
        this.changeActive(true);
      }else this.props.pageSize=5;
    } else if (name === 'total') {
      if (this.isPositiveInteger(cur)) {
        this.props.total = Math.ceil(Number(cur));
        this.props.pageSize
          ? (this.props.pageCount = Math.ceil(this.props.total / this.props.pageSize))
          : null;
        this.changeActive(true);
        const total = this._sd.querySelector('.cms-pagination-totalContainer');
        total.innerHTML = `共 ${this.props.total} 条`;
      } else this.props.total = 0;
    } else if (name === 'current-page') {
      if (this.isPositiveInteger(cur)) {
        if(Math.round(Number(cur))<=this.props.pageCount){
          this.props.currentPage = Math.round(Number(cur));
          this.changeActive();
        }
      }else this.props.currentPage=1;
    } else if (name === 'pager-count') {
      if (this.isPositiveInteger(cur) && cur >= 3) {
        if ((cur - 1) % 2 === 0) {
          this.props.pagerCount = Math.round(Number(cur));
        } else {
          this.props.pagerCount = Math.round(Number(cur)) + 1;
        }
      } else {
        this.props.pagerCount = 3;
      }
      this.changeActive(true);
    } else if (name === 'page-sizes') {
      if (cur) {
        let arr=[];
        if (Array.isArray(cur)){
          arr = cur;
        }else{
          if(cur.slice(0,1)=='['){
            arr = cur.slice(1, -1).split(',').map(i => +i);
          }else{
            arr = cur.split(',').map(i => +i);
          }
        }
        this.props.pageSizes = arr;
        this.pageSize = arr[0];
        this.renderSelectDom();
      } else {
        const select = this._sd.querySelector('#cms-pagination-select');
        select.remove();
      }
    }
  }
  //用于判断属性值是否为大于0的数
  isPositiveInteger(cur) {
    const curNum = Number(cur);
    return Boolean(!isNaN(curNum) && curNum > 0);
  }
  //提取renderPageButton函数中渲染中间部分按钮功能
  renderCenterPart(props, type, domStructure) {
    const numSpan = this._sd.querySelector('.cms-numContainer');
    const typeArr = {
      1: props.currentPage - 1,
      2: props.pagerCount - props.pageCount + props.currentPage - 1,
      3: (props.pagerCount + 1) / 2 - 1,
    };
    numSpan.innerHTML = domStructure;
    const numDom = this._sd.querySelectorAll('.cms-pagination-pageButton');
    numDom[typeArr[type]]?.setAttribute('active', true);
  }
  //提取对domStructure的操作
  connectDomStructure(props, type, domStructure, i) {
    const typeArr = {
      1: i,
      2: i + 1,
      3: props.pageCount,
      4: props.pageCount - props.pagerCount + 1 + i,
      5: props.currentPage - (props.pagerCount - 3) / 2 + i - 1,
    };
      domStructure =
        domStructure +
        `<li class="cms-pagination-pageButton cms-pagination-clickButton" key=${typeArr[type]}>第${typeArr[type]}页</li>`;
    return domStructure;
  }
  /**innerHTML内容：首先看总页数是不是小于规定展示的页面数量，如果不是，则执行下面逻辑：
   *                1.如果currentPage<=(pagerCount+1)/2，则在左边，直接顺序展示pagerCount-2个；
   *                2.currentPage>(pagerCount+1)/2且（pageCount-currentPage）<=(pagerCount-1)/2 则在右边，直接倒序展示pagerCount-2个；
   *                3.剩下的在中间，以currentPage为基准共展示pagerCount-2个；；若pagerCount=3，则只展示currentPage；
   **/
  renderPageButton(props) {
    let domStructure = '';
    if (props.pageCount <= props.pagerCount) {
      for (let i = 1; i <= props.pageCount; i++) {
        domStructure = this.connectDomStructure(props, 1, domStructure, i);
      }
      this.renderCenterPart(props, 1, domStructure);
    } else {
      domStructure = '<li class="cms-pagination-pageButton cms-pagination-clickButton" key="1">第1页</li>';
      if (props.currentPage <= (props.pagerCount + 1) / 2) {
        //右边加省略号，active属性直接加在对应下标的元素上
        for (let i = 1; i <= props.pagerCount - 2; i++) {
          domStructure = this.connectDomStructure(props, 2, domStructure, i);
        }
        domStructure = domStructure + `${ellipsis}`;
        domStructure = this.connectDomStructure(props, 3, domStructure);
        this.renderCenterPart(props, 1, domStructure);
      } else if (props.pageCount - props.currentPage <= (props.pagerCount - 1) / 2) {
        //左边加省略号，active属性加的下标根据currentPage和pageCount以及pagerCount共同确定
        domStructure = domStructure +  `${ellipsis}`;
        for (let i = 1; i <= props.pagerCount - 2; i++) {
          domStructure = this.connectDomStructure(props, 4, domStructure, i);
        }
        domStructure = this.connectDomStructure(props, 3, domStructure);
        this.renderCenterPart(props, 2, domStructure);
      } else {
        //两边加省略号，active属性加在列表中间的元素
        domStructure = domStructure +  `${ellipsis}`;
        for (let i = 1; i <= props.pagerCount - 2; i++) {
          domStructure =  this.connectDomStructure(props, 5, domStructure, i);
        }
        domStructure = domStructure +  `${ellipsis}`;
        domStructure = this.connectDomStructure(props, 3, domStructure);
        this.renderCenterPart(props, 3, domStructure);
      }
    }
  }
  //给当前按钮添加active属性，并执行renderPageButton函数更新按钮dom结构
  changeActive = set => {
    this.renderPageButton(this.props);
    this.addListener(this);
    const numDom = this._sd.querySelectorAll('.cms-pagination-pageButton');
    set && numDom[0]?.setAttribute('active', true);
    numDom?.forEach(cur => {
      cur.getAttribute('active')
        ? cur.setAttribute('class', 'cms-pagination-pageButton cms-pagination-clickButton cms-pagination-active')
        : cur.setAttribute('class', 'cms-pagination-pageButton cms-pagination-clickButton');
    });
  };
  //点击下一页按钮时的回调函数
  nextDomFunc = () => {
    if(this.props.currentPage < this.props.pageCount){
      this.currentPage++;
      this.dispatchEvent(RateEvent('next-click', this.props));
    }
  };
  //点击上一页按钮时的回调函数
  prevDomFunc = () => {
    if(this.props.currentPage > 1){
      this.currentPage--;
      this.dispatchEvent(RateEvent('prev-click', this.props));
    }
  };
  //中间数字按钮的回调函数
  numDomFunc = e => {
    if (this.props.currentPage != Number(e.target.getAttribute('key'))){
      this.currentPage = Number(e.target.getAttribute('key'));
      this.changeActive();
    }
  };
  //用于给分页按钮绑定点击事件
  addListener(that) {
    const numDom = this._sd.querySelectorAll('.cms-pagination-pageButton');
    const prevDom = this._sd.querySelector('#cms-pagination-prevButton');
    const nextDom = this._sd.querySelector('#cms-pagination-nextButton');
    nextDom?.removeEventListener('click', that.nextDomFunc);
    prevDom?.removeEventListener('click', that.prevDomFunc);
    numDom.forEach(cur => {
      cur.removeEventListener('click', that.numDomFunc);
    });

    numDom.forEach((cur)=>{
      cur.addEventListener('click', that.numDomFunc);
    });

    nextDom?.addEventListener('click', that.nextDomFunc);
    prevDom?.addEventListener('click', that.prevDomFunc);
  }
  //用于渲染pageSize下拉选择框
  renderSelectDom() {
    const outerSpan = this._sd.querySelector('#cmsPagination');
    const select = document.createElement('select');
    select.setAttribute('id', 'cms-pagination-select');
    select.setAttribute('name', 'pagination-page-sizes');
    //给下拉框一个数值列表；遍历数组插入option标签；
    this.props.pageSizes.forEach(cur => {
      const option = document.createElement('option');
      option.setAttribute('value', cur);
      option.innerHTML = `${cur} 条/页`;
      select.appendChild(option);
    });
    outerSpan.appendChild(select);
    //监听select的change事件，change时对pagesize值进行同步更新
    select.addEventListener('change', () => {
      const options = select.querySelectorAll('option');
      this.pageSize = +options[select.selectedIndex].getAttribute('value');
    });
  }
  constructor() {
    super();
    this._sd = this.attachShadow({ mode: 'closed' });
    this.renderStyle();
    this.renderDom();
    this.addListener(this);
  }
  renderStyle() {
    // 保证shadow dom中只存在一个style标签
    let style = this._sd.querySelector('style');
    if (!style) {
      style = document.createElement('style');
      this._sd.appendChild(style);
    }
    // 用于css的属性值
    const styleProps = { ...this.props, ...this.global };
    // 生成css样式。可以自定义的样式通过css变量的形式定义
    style.innerHTML = createDOMString(styleProps)`
      :host {
        width: 100%;
        height: 100%;
      }
      :host .cms-pagination-space {
        margin:2px;
      }
      :host>.cms-pagination-container {
        display:flex;
        height:25px;
        line-height:25px;
        font-size:14px;
      }
      :host>.cms-pagination-container> .cms-pagination-totalContainer {
        font-size: 12px;
        margin-right: 8px;
      }
      :host>.cms-pagination-container .cms-pagination-clickButton{
        min-width:32px; 
        margin:0 4px;
        padding:0 3px;
        border:0;
        border-radius: 2px;
        background-color: #f0f2f5;
        color: #606266;
        cursor:pointer;
      }
      :host> .cms-pagination-container> .cms-numContainer {
        display:flex;
        margin:0;
        padding:0;
      }
      :host>.cms-pagination-container> #cms-pagination-select {
        min-width: 100px;
        margin-left: 8px;
        text-align: center;
        border: 1px solid rgb(201, 205, 211);
        border-radius: 2px;
      }
      :host> .cms-pagination-container> .cms-numContainer> .cms-pagination-pageButton {
        list-style: none;
      }
      :host> .cms-pagination-container> .cms-numContainer> .cms-pagination-active {
        background-color: #c9000d;
        color: #ffffff;
      }
    `;
  }
  renderDom() {
    const template = document.createElement('template');
    template.innerHTML = `
      <span class="cms-pagination-container" id="cmsPagination">
        <span class="cms-pagination-totalContainer">
          共 ${this.props.total} 条 
        </span>
        <button id="cms-pagination-prevButton" class="cms-pagination-clickButton">上一页</button>
        <ul class="cms-numContainer"></ul>
        <button id="cms-pagination-nextButton" class="cms-pagination-clickButton">下一页</button>
      </span>`;
    this._sd.appendChild(template.content.cloneNode(true));
    this.changeActive(true);
  }
}


customElements.define('cms-pagination', CmsPagination); 